//
// Created by jaesonzhang on 2024/3/19.
//

#include "SQLiteManager.h"

SQLiteManager::SQLiteManager(const std::string &db_path) : stop_thread_(false) {
    if (sqlite3_open(db_path.c_str(), &db_) != SQLITE_OK) {
        std::cerr << "Cannot open database: " << sqlite3_errmsg(db_) << std::endl;
        sqlite3_close(db_);
        db_ = nullptr;
    } else {
        // 启动数据库线程
        db_thread_ = std::thread(&SQLiteManager::processTasks, this);
    }
}

SQLiteManager::~SQLiteManager() {
    // 停止数据库线程
    {
        std::lock_guard<std::mutex> lock(task_mutex_);
        stop_thread_ = true;
    }
    task_cv_.notify_one();
    if (db_thread_.joinable()) {
        db_thread_.join();
    }

    if (db_) {
        sqlite3_close(db_);
    }
}

// 异步执行SQL查询
std::future<void> SQLiteManager::executeAsync(const std::string &sql) {
    std::packaged_task<void()> task([this, sql] {
        char *errmsg;
        int rc = sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &errmsg);
        if (rc != SQLITE_OK) {
            std::cerr << "SQL error: " << errmsg << std::endl;
            sqlite3_free(errmsg);
        }
    });

    auto future = task.get_future();
    enqueueTask(std::move(task));
    return future;
}

// 异步准备SQL语句
std::future<sqlite3_stmt *> SQLiteManager::prepareAsync(const std::string &sql) {
    std::packaged_task<sqlite3_stmt *()> task([this, sql] {
        sqlite3_stmt *stmt = nullptr;
        if (sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
            std::cerr << "Failed to prepare statement: " << sqlite3_errmsg(db_) << std::endl;
            return static_cast<sqlite3_stmt *>(nullptr);
        }
        return stmt;
    });

    auto future = task.get_future();
    enqueueTask(std::move(task));
    return future;
}

// 将任务添加到队列中
template<typename T>
void SQLiteManager::enqueueTask(T &&task) {
    {
        std::lock_guard<std::mutex> lock(task_mutex_);
        tasks_.emplace(std::move(task)); // 使用 std::move 来移动任务
    }
    task_cv_.notify_one();
}

// 数据库线程的主循环
void SQLiteManager::processTasks() {
    while (true) {
        std::packaged_task<void()> task;
        {
            std::unique_lock<std::mutex> lock(task_mutex_);
            task_cv_.wait(lock, [this] { return stop_thread_ || !tasks_.empty(); });
            if (stop_thread_ && tasks_.empty()) {
                break;
            }
            task = std::move(tasks_.front()); // 使用 std::move 来移动任务
            tasks_.pop();
        }
        task(); // 执行任务
    }
}